package com.ruoyi.framework.security.service

import com.ruoyi.common.utils.SecurityUtils
import com.ruoyi.common.utils.StringUtils
import com.ruoyi.framework.security.context.PermissionContextHolder
import org.springframework.stereotype.Service
import org.springframework.util.CollectionUtils

/**
 * RuoYi首创 自定义权限实现，ss取自SpringSecurity首字母
 *
 * @author ruoyi
 */
@Service("ss")
class PermissionService {

    companion object {
        /** 所有权限标识  */
        private const val ALL_PERMISSION = "*:*:*"

        /** 管理员角色权限标识  */
        private const val SUPER_ADMIN = "admin"
        private const val ROLE_DELIMETER = ","
        private const val PERMISSION_DELIMETER = ","
    }

    /**
     * 验证用户是否具备某权限
     *
     * @param permission 权限字符串
     * @return 用户是否具备某权限
     */
    fun hasPermi(permission: String?): Boolean {
        when {
            StringUtils.isEmpty(permission) -> {
                return false
            }
            else -> {
                val loginUser = SecurityUtils.getLoginUser()
                return when {
                    StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(
                        loginUser.permissions
                    )
                    -> {
                        false
                    }

                    else -> {
                        PermissionContextHolder.setContext(permission!!)
                        hasPermissions(loginUser.permissions!!, permission)
                    }
                }
            }
        }
    }

    /**
     * 验证用户是否不具备某权限，与 hasPermi逻辑相反
     *
     * @param permission 权限字符串
     * @return 用户是否不具备某权限
     */
    fun lacksPermi(permission: String?): Boolean {
        return !hasPermi(permission)
    }

    /**
     * 验证用户是否具有以下任意一个权限
     *
     * @param permissions 以 PERMISSION_NAMES_DELIMETER 为分隔符的权限列表
     * @return 用户是否具有以下任意一个权限
     */
    fun hasAnyPermi(permissions: String): Boolean {
        when {
            StringUtils.isEmpty(permissions) -> {
                return false
            }
            else -> {
                val loginUser = SecurityUtils.getLoginUser()
                return when {
                    StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(
                        loginUser.permissions
                    )
                    -> {
                        false
                    }
                    else -> {
                        val authorities = loginUser.permissions
                        permissions.split(PERMISSION_DELIMETER.toRegex())
                            .dropLastWhile { it.isEmpty() }
                            .toTypedArray().any { hasPermissions(authorities!!, it) }
                    }
                }
            }
        }
    }

    /**
     * 判断用户是否拥有某个角色
     *
     * @param role 角色字符串
     * @return 用户是否具备某角色
     */
    fun hasRole(role: String?): Boolean {
        when {
            StringUtils.isEmpty(role) -> {
                return false
            }
            else -> {
                val loginUser = SecurityUtils.getLoginUser()
                return when {
                    StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(
                        loginUser.user!!.roles
                    )
                    -> {
                        false
                    }

                    else -> loginUser.user!!.roles!!
                        .asSequence()
                        .map { it.roleKey }
                        .any { SUPER_ADMIN == it || it == StringUtils.trim(role) }
                }
            }
        }
    }

    /**
     * 验证用户是否不具备某角色，与 isRole逻辑相反。
     *
     * @param role 角色名称
     * @return 用户是否不具备某角色
     */
    fun lacksRole(role: String?): Boolean {
        return !hasRole(role)
    }

    /**
     * 验证用户是否具有以下任意一个角色
     *
     * @param roles 以 ROLE_NAMES_DELIMETER 为分隔符的角色列表
     * @return 用户是否具有以下任意一个角色
     */
    fun hasAnyRoles(roles: String): Boolean {
        when {
            StringUtils.isEmpty(roles) -> {
                return false
            }
            else -> {
                val loginUser = SecurityUtils.getLoginUser()
                return when {
                    StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(
                        loginUser.user!!.roles
                    )
                    -> {
                        false
                    }

                    else -> roles.split(ROLE_DELIMETER.toRegex()).dropLastWhile { it.isEmpty() }
                        .toTypedArray().any { hasRole(it) }
                }
            }
        }
    }

    /**
     * 判断是否包含权限
     *
     * @param permissions 权限列表
     * @param permission 权限字符串
     * @return 用户是否具备某权限
     */
    private fun hasPermissions(permissions: Set<String?>, permission: String?): Boolean {
        return permissions.contains(ALL_PERMISSION) || permissions.contains(
            StringUtils.trim(
                permission
            )
        )
    }
}
